#include "blockingQueue.h"

void initList(linkList* list){
	list->size = 0;
	list->head = NULL;
	list->tail = NULL;
}

/**
 * this method will add node to the tail of the list.
 * node->next will point to null at the end of this function
 * */
void addNode(linkList * list, llNode * node){
	if (list->size == 0){
		list->head = node;
		list->tail = node;
	}
	else
		list->tail->next = node;
	node->next = NULL;
	list->tail = node;
	list->size++;
}

llNode* removeNode(linkList* list){
	if (list->size > 0){
		llNode* res = list->head;
		list->head = res->next;
		list->size--;
		return res;
	}
	return NULL;
}


void initBQueue(blockingQueue* queue){
	queue->list = malloc(sizeof(linkList));
	initList(queue->list);
	queue->sem = malloc(sizeof(sem_t));
    sem_init(queue->sem, 0, 0);
    queue->mutex = malloc(sizeof(pthread_mutex_t));
    pthread_mutex_init(queue->mutex, NULL);
}

void killBQueue(blockingQueue* queue)
{
	if (queue != NULL)
	{
		free(queue->list);
		sem_destroy(queue->sem);
		free(queue->sem);
		pthread_mutex_destroy(queue->mutex);
		free(queue->mutex);
	}
	free(queue);
}

void bqueueEnqueue(blockingQueue * queue, llNode * node){
	 pthread_mutex_lock(queue->mutex);
	 addNode(queue->list,node);
	 sem_post(queue->sem);
	 pthread_mutex_unlock(queue->mutex);
}
llNode* bqueueDequeue(blockingQueue* queue){
	sem_wait(queue->sem);
	pthread_mutex_lock(queue->mutex);
	llNode* res = removeNode(queue->list);
	pthread_mutex_unlock(queue->mutex);
	return res;
}


